package com.atguigu.gulimall.order.controller;

import com.alibaba.fastjson.JSON;
import com.atguigu.gulimall.order.entity.OrderEntity;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.util.Date;
import java.util.UUID;

@Controller
public class RabbitController {

//    @Autowired
    AmqpAdmin amqpAdmin;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @ResponseBody
    @GetMapping("/test/createOrder")
    public String createOrderTest(){

        OrderEntity entity = new OrderEntity();
        entity.setOrderSn(UUID.randomUUID().toString());
        entity.setModifyTime(new Date());

        //发送消息给MQ
        rabbitTemplate.convertAndSend("order-event-exchange","order.create.order",entity);

        return "ok";
    }





    /**
     * 1。如何创建Exchange Queue Binding
     *      1。使用AmqpAdimn进行创建
     * 2。如何收发消息
     */

    /**
     * 接收消息时参数可以写以下类型
     *使用@RabbitListener(queues = {"hello-java-queue"})一个注解
     * queues为接收队列的数组
     *
     * 1。org.springframework.amqp.core.Message---需要转换
     *
     * 2。发消息时发的时什么类型，就可以用什么类型接收----不用手动转换
     * T<发送消息的类型>
     *
     * 3。Channel channel：传输数据的通道
     * com.rabbitmq.client.Channel
     *
     * Queue：可以很多人都来监听，只要收到消息，队列就会删除消息，而且只能有一个人收到消息
     *  场景：
     *  1。订单服务启动多个：同一个消息，只能有一个客户端收到
     *  2。接收消息都业务处理很耗时，在业务处理期间能不能收到其他消息
     *    --只有当消息处理完了，才可以接收下一个消息
     */
    @RabbitListener(queues = {"hello-java-queue"})
    @RabbitHandler
    public void testRecieveMessage(Message message,
                            OrderEntity content,
                            Channel channel) {

        byte[] body = message.getBody();
        Object o = JSON.parseObject(body, OrderEntity.class);

        System.out.println(content);
        System.out.println(o);
    }

    @RabbitHandler
    public void testRecieveMessage(Message message,String  content,Channel channel) {

        System.out.println(content);

        try {
            //手动接收模式下，通过通道来确认签收
            //自增的，通道channel内按顺序自增
            long deliveryTag = message.getMessageProperties().getDeliveryTag();
            if (deliveryTag % 2 == 0){
                //签收
                //参数二：是否批量签收，false非批量签收
                channel.basicAck(deliveryTag,false);
            }else {
                //拒绝签收
                //参数二：是否批量拒绝，拒绝所有都拒绝
                //参数三：false：消息丢弃 ，true：发回服务器，消息重新入队,入队后的消息又会重新发给消费端
                channel.basicNack(deliveryTag,false,false);
                //方法同basicNack，拒收，区别：不可以批量
                channel.basicReject(deliveryTag,false);
            }

        } catch (IOException e) {
            e.printStackTrace();
            //网络中断。。。。异常
        }
    }

    /**
     * 发送消息
     */
    @ResponseBody
    @GetMapping("/test/sendMessage")
    public String testSendMessage(){
        //转换并发送
        String msg = "xxxxxxxx";

        //发送的消息对象，会使用序列化机制，对象需要实现Serializable接口
        //想让发送出去的对象用json序列化
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setBillContent("111");
        orderEntity.setAutoConfirmDay(2);
        orderEntity.setBillHeader("ddddd");

        //CorrelationData消息的唯一id
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0){
                rabbitTemplate.convertAndSend("hello-java-exchange","hello-java",orderEntity,new CorrelationData(UUID.randomUUID().toString()));
            }else {
                rabbitTemplate.convertAndSend("hello-java-exchange","hello-java",msg,new CorrelationData(UUID.randomUUID().toString()));
            }
        }

        return "ok";
    }

    /**
     * 创建交换机
     * [hello-java-exchange]
     */
    @ResponseBody
    @GetMapping("/test/crateExchange")
    public String crateExchange(){
        //amqpAdmin
        DirectExchange directExchange = new DirectExchange("hello-java-exchange",true,false);
        amqpAdmin.declareExchange(directExchange);

        return "ok";
    }

    /**
     * 创建队列
     * [hello-java-exchange]
     */
    @ResponseBody
    @GetMapping("/test/crateQueue")
    public String crateQueue(){
        //amqpAdmin
        Queue queue = new Queue("hello-java-queue",true,false,false);
        amqpAdmin.declareQueue(queue);

        return "ok";
    }

    /**
     * 创建绑定关系
     * [hello-java-exchange]
     */
    @ResponseBody
    @GetMapping("/test/crateBanding")
    public String crateBanding(){
        //Binding(String destination, Binding.DestinationType destinationType, String exchange, String routingKey, Map<String, Object> arguments) {
        //        this.destination = destination;
        /**
         * destination:目的地 队列的名字
         * DestinationType：目的地类型 队列类型
         * exchange：交换机
         * routingKey：路由键
         * arguments：自定义参数
         */
        Binding binding = new Binding("hello-java-queue",
                Binding.DestinationType.QUEUE,
                "hello-java-exchange",
                "hello-java",
                null);
        amqpAdmin.declareBinding(binding);

        return "ok";
    }
}
